package com.wtao.imagereader;

import android.Manifest;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.ImageFormat;
import android.graphics.SurfaceTexture;
import android.hardware.camera2.CameraAccessException;
import android.hardware.camera2.CameraCaptureSession;
import android.hardware.camera2.CameraCharacteristics;
import android.hardware.camera2.CameraDevice;
import android.hardware.camera2.CameraManager;
import android.hardware.camera2.CameraMetadata;
import android.hardware.camera2.CaptureRequest;
import android.hardware.camera2.CaptureResult;
import android.hardware.camera2.TotalCaptureResult;
import android.media.Image;
import android.media.ImageReader;
import android.media.MediaCodec;
import android.media.MediaRecorder;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.HandlerThread;
import android.text.TextUtils;
import android.util.Log;
import android.util.Size;
import android.util.SparseIntArray;
import android.view.Surface;
import android.view.TextureView;
import android.view.View;
import android.view.WindowManager;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import com.wtao.imagereader.utils.PhotoUtil;
import com.wtao.imagereader.utils.YUVTools;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;


/**
 * 拍照 在ImageReader里拿到byte[]保存图片的方式拍照
 */
public class TakePhotoActivity extends AppCompatActivity implements ImageReader.OnImageAvailableListener {
    private static final String TAG = "TakePhotoActivity";


    private Context mContext;
    private CameraManager mCameraManager;
     private int mCurrentCameraId = 2;

    private CameraDevice mCurrentCameraDevice;
    private CaptureRequest mCurrentPreviewRequest;
    private TextureView mTextureView;
    private Surface mPreviewSurface;
    private CameraCaptureSession mCurrentCameraCaptureSession;

    private Button mBtnTakePicture;
    private int previewWidth = 1920;
    private int previewHeight = 1080;
    private Size mVideoSize ;

    private boolean isRecording = false;
    private MediaRecorder mMediaRecorder;

    HandlerThread mBackgroundThread;
    Handler mBackgroundHandler;
    ImageReader imageReader;
    boolean saveImageFlag = false;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_take_photo);
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
        this.mContext = this;
        if (getIntent() != null) {
            String cameraIdStr = getIntent().getStringExtra("dmsCameraID");
             if (TextUtils.isEmpty(cameraIdStr)) {
                cameraIdStr = "2";
            }
            Log.e(TAG, "getIntent() != null cameraIdStr="+cameraIdStr);
            mCurrentCameraId = Integer.parseInt(cameraIdStr);

            String widthStr = getIntent().getStringExtra("width");
            if (TextUtils.isEmpty(widthStr)) {
                widthStr = "1920";
            }
            previewWidth = Integer.parseInt(widthStr);

            String heightStr = getIntent().getStringExtra("height");
            if (TextUtils.isEmpty(heightStr)) {
                heightStr = "1080";
            }
            previewHeight =Integer.parseInt(heightStr);
            mVideoSize = new Size(previewWidth,previewHeight);

        } else {
            mCurrentCameraId = 0;
            previewWidth = 1920;
            previewHeight = 1080;
            mVideoSize = new Size(1920,1080);
        }
        initView();
        initCamera();
        startBackgroundThread();
    }
    /**
     * Starts a background thread and its {@link Handler}.
     */
    private void startBackgroundThread() {
        mBackgroundThread = new HandlerThread("CameraBackground");
        mBackgroundThread.start();
        mBackgroundHandler = new Handler(mBackgroundThread.getLooper());
    }

    /**
     * Stops the background thread and its {@link Handler}.
     */
    private void stopBackgroundThread() {
        mBackgroundThread.quitSafely();
        try {
            mBackgroundThread.join();
            mBackgroundThread = null;
            mBackgroundHandler = null;
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        stopBackgroundThread();
        closeCamera();
    }

    private void initView() {
        mTextureView = findViewById(R.id.texture);
        mTextureView.setSurfaceTextureListener(new TextureView.SurfaceTextureListener() {
            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) {
                // 这里解释一下，为什么摄像头打开的时候没有马上打开预览，因为预览画面的展示需要 surface 承载，所以需要等 surface 准备好才行
                surface.setDefaultBufferSize(mVideoSize.getWidth(),mVideoSize.getHeight());
                // 预览所需的 previewSurface
                mPreviewSurface = new Surface(surface);
                openCamera();
            }

            @Override
            public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) {

            }

            @Override
            public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surface) {
                mPreviewSurface.release();
                mPreviewSurface = null;
                return false;
            }

            @Override
            public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surface) {

            }
        });
        findViewById(R.id.bt_back).setOnClickListener(v->{
            finish();
        });
        mBtnTakePicture = findViewById(R.id.btnTakePhoto);
        mBtnTakePicture.setOnClickListener(new View.OnClickListener() {
            @RequiresApi(api = Build.VERSION_CODES.M)
            @Override
            public void onClick(View v) {
                Log.d(TAG, "onClick: 点击拍照");
                saveImageFlag = true;
            }
        });
    }

    private void initCamera() {
        // 1. 先获取 CameraManager
        mCameraManager = (CameraManager) mContext.getSystemService(Context.CAMERA_SERVICE);
        if (mCameraManager == null) {
            return;
        }

    }

    private void openCamera(){
        closeCamera();
        Log.e(TAG, "openCamera");
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) {
            return;
        }
        try {
            // 2. 调用 openCamera，打开摄像头
            mCameraManager.openCamera(String.valueOf(mCurrentCameraId), new CameraDevice.StateCallback() {
                @RequiresApi(api = Build.VERSION_CODES.M)
                @Override
                public void onOpened(@NonNull CameraDevice camera) {
                    Log.d(TAG, "onOpened: 摄像头链接成功, facing: " + mCurrentCameraId);
                    // 摄像头成功打开
                    mCurrentCameraDevice = camera;
                    // 准备视频录制时所需的 recordSurface
                    startPreview();
                }

                @Override
                public void onDisconnected(@NonNull CameraDevice camera) {
                    Log.d(TAG, "onDisconnected: 摄像头链接断开");
                }

                @Override
                public void onError(@NonNull CameraDevice camera, int error) {
                    Log.d(TAG, "onError: 摄像头打开失败, error: " + error);
                    camera.close();
                }
            }, null);
        } catch (CameraAccessException e) {
            Log.e(TAG, "openCamera: ", e);
        }
    }

    private void startPreview(){
        Log.e(TAG, "startPreview()");
        if(mCurrentCameraDevice == null){
            Log.e(TAG , "mCurrentCameraDevice null");
            return;
        }
        if(mPreviewSurface == null){
            Log.e(TAG , "mPreviewSurface null");

            return;
        }
        try {
            imageReader =ImageReader.newInstance(previewWidth, previewHeight,
                    ImageFormat.YUV_420_888, /*maxImages*/2);
            imageReader.setOnImageAvailableListener(this, mBackgroundHandler);
            // 3. 创建session，可以看到这里绑定了两个 surface，一个用于承载预览显示，一个用于视频录制
            List<Surface> mOutputs = new ArrayList<>();
            mOutputs.add(mPreviewSurface);
            mOutputs.add(imageReader.getSurface());
            mCurrentCameraDevice.createCaptureSession(mOutputs, new CameraCaptureSession.StateCallback() {
                @Override
                public void onConfigured(@NonNull CameraCaptureSession session) {
                    Log.e(TAG, "createCaptureSession onConfigured ");
                    mCurrentCameraCaptureSession = session;
                    try {
                        // 4. 开启预览
                        createPreviewCaptureRequest();
                        mCurrentCameraCaptureSession.setRepeatingRequest(mCurrentPreviewRequest, null, mBackgroundHandler);
                    } catch (CameraAccessException e) {
                        Log.e(TAG, "onConfigured: ", e);
                    }
                }

                @Override
                public void onConfigureFailed(@NonNull CameraCaptureSession session) {
                    Log.e(TAG, "createCaptureSession onConfigureFailed ");

                }
            }, null);
        } catch (CameraAccessException e) {
            Log.e(TAG, "startPreview: ", e);
        }
    }

    /**
     * 用于预览显示的request
     */
    private void createPreviewCaptureRequest() {
        try {
            Log.e(TAG, "createPreviewCaptureRequest");
            CaptureRequest.Builder mCurrentPreviewRequestBuilder = mCurrentCameraDevice.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW);
            mCurrentPreviewRequestBuilder.addTarget(mPreviewSurface);
            mCurrentPreviewRequestBuilder.addTarget(imageReader.getSurface());
            mCurrentPreviewRequest = mCurrentPreviewRequestBuilder.build();
        } catch (CameraAccessException e) {
            Log.e(TAG, "createPreviewCaptureRequest: ", e);
        }
    }



    private void closeCamera(){
        if(mCurrentCameraDevice != null){
            mCurrentCameraDevice.close();
            mCurrentCameraDevice = null;
        }
    }

    @Override
    protected void onResume() {
        super.onResume();

    }

    @Override
    protected void onPause() {
        super.onPause();
        closeCamera();
        if(mMediaRecorder != null){
            mMediaRecorder.release();
            mMediaRecorder = null;
        }

    }




    @Override
    public void onImageAvailable(ImageReader reader) {
        Image image = reader.acquireLatestImage();
        if (image == null) {
            return;
        }
        //Log.e(TAG, "onImageAvailable");

        if(saveImageFlag){
            Log.e(TAG, "保存图片");
            saveImageFlag = false;
            String path = PhotoUtil.saveYuvImage(image);
            Log.e(TAG, "path="+path);
        }
        image.close();
    }
}